#include <iostream>
#include <vector>

class Foo {
  int x_;

public:
  Foo(int const x = 0) : x_{x} {}
  int &get() { return x_; }
};

void test_foo() {
  Foo f(42);
  auto x = f.get();
  x = 100;
  std::cout << f.get() << std::endl; // 42
  auto &x1 = f.get();
  x1 = 200;
  std::cout << f.get() << std::endl; // 200
}

// auto proxy_get(Foo &f) { return f.get(); }
decltype(auto) proxy_get(Foo &f) { return f.get(); }
void test_proxy_get() {
  Foo f(42);
  // auto &x = proxy_get(f);  // 报错
  decltype(auto) x = proxy_get(f);
}

int main(int argc, char *argv[]) {
  std::cout << "Hello, world!" << std::endl;

  auto i = 42;        // int
  auto d = 3.14;      // double
  auto s = "text";    // const char*
  auto v = {1, 2, 3}; // std::initializer_list<int>

  auto b = new char[10]{};             // char*
  auto s1 = std::string{"text"};       // std::string
  auto v1 = std::vector<int>{1, 2, 3}; // std::vector<int>
  auto p = std::make_unique<int>(42);  // std::unique_ptr<int>

  auto upper = [](char const c) { return std::toupper(c); };

  auto add = [](auto const a, auto const b) { return a + b; };

  test_foo();

  // 不清楚下面的对不对, 书上说是错的, 但是编译可以通过...
  // auto ai = std::atomic<int>{42}; // error
  // auto l1 = long long{42};        // error
  using llong = long long;
  auto l2 = llong{42}; // ok

  return 0;
}

template <typename F, typename T> auto apply(F &&f, T value) {
  return f(value);
}
